package fina2.upload;

import java.io.File;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Synchronized;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;

import fina2.dcs.common.security.UserType;
import fina2.dcs.common.security.UserUtil;
import fina2.dcs.common.xls.XLSValidator;
import fina2.dcs.fis.BankLocal;
import fina2.dcs.security.RoleLocal;
import fina2.dcs.security.User;
import fina2.dcs.security.UserLocal;
import fina2.dcs.system.SysProperty;
import fina2.dcs.system.SysPropertyLocal;
import fina2.dcs.system.SysUserBankLocal;
import fina2.dcs.upload.UploadFileStatus;
import fina2.dcs.upload.UploadedFile;
import fina2.dcs.upload.UploadedFileLocal;

@Name("uploadBean")
@Scope(ScopeType.SESSION)
@Synchronized(timeout = 1000000000)
@SuppressWarnings("serial")
public class UploadBean implements Serializable {

	private Log log = null;

	private ArrayList<Long> filesToRemove = new ArrayList<Long>();

	private List<String> invalidFiles = new ArrayList<String>();
	private String unconfirmedSheets = null;

	private String fileToRemove = null;

	private Map<String, String> validationProperties = null;
	private List<String> patterns = new ArrayList<String>();
	private List<UploadedFile> files = new ArrayList<UploadedFile>();
	private int pageIndex = 1;
	private int maxPages = 100;

	private List<SelectItem> users = null;
	private List<SelectItem> banks = null;
	private List<SelectItem> statuses = null;
	private List<SelectItem> periodCriterias = null;

	private Date toDate = new Date();
	private Date fromDate = new Date();

	private String username;

	private String selectedStatus = "ALL";
	private String selectedUser = "ALL";
	private BigDecimal selectedUserId = null;
	private String selectedBank = "ALL";

	public static String status = "";

	private String filename;

	private UploadedFileLocal ufl = null;
	private BankLocal bankLocal = null;
	private UserLocal ul = null;
	private RoleLocal roleLocal = null;
	private SysUserBankLocal sysUserBankLocal = null;
	private ResourceBundle bundle = null;
	private SysPropertyLocal sysPropLocal = null;

	private boolean hasUserBank = false;
	private boolean xlsProtPasswValid = false;
	private boolean xlsProtected = false;
	private boolean xlsFileNameValid = false;
	private boolean xlsFile = false;
	private boolean xlsMatrixValid = false;
	private String matrixReason = null;

	private long converted;
	private long rejected;
	private long uploaded;
	private long uploadedAndConverted;
	private long uploadedErrorInProcessing;
	private long uploadedAndNotConverted;
	private long uploadedAndNotValidated;
	private long uploadedAndProcessed;
	private long uploadedAndValidated;
	private long all;
	private UploadedFile uploadedFile = null;

	public String getUnconfirmedSheets() {
		return unconfirmedSheets;
	}

	public void setUnconfirmedSheets(String unconfirmedSheets) {
		this.unconfirmedSheets = unconfirmedSheets;
	}

	public static String getStatus() {
		return status;
	}

	public static void setStatus(String status) {
		UploadBean.status = status;
	}

	public void refreshData() {
		log.info("Refreshing Data");
		selectedBank = "ALL";
		createComponents();
		log.info("Data Refreshed");
	}

	@Create
	public void createComponents() {
		try {
			log = Logging.getLog(getClass());
			UIViewRoot vr = FacesContext.getCurrentInstance().getViewRoot();
			Locale l = vr.getLocale();
			ClassLoader cl = Thread.currentThread().getContextClassLoader();
			bundle = ResourceBundle.getBundle("messages", l, cl);

			ul = (UserLocal) Component.getInstance("userSession");// ContextHelper.injectUserLocal(jndi);
			roleLocal = (RoleLocal) Component.getInstance("roleSession");
			ufl = (UploadedFileLocal) Component.getInstance("uploadFileSession");// ContextHelper.injectUploadedFileLocal(jndi);
			sysUserBankLocal = (SysUserBankLocal) Component.getInstance("sysUsrBank");// ContextHelper.injectSysUserBankLocal(jndi);
			sysPropLocal = (SysPropertyLocal) Component.getInstance("propSession");// ContextHelper.injectSysPropLocal(jndi);
			bankLocal = (BankLocal) Component.getInstance("bankSession");// ContextHelper.injectBankLocal(jndi);
			selectedUser = ul.getCurrentUser().getLogin();
			uploadedFile = new UploadedFile();

			uploadedFile.setFromDate(fromDate);
			uploadedFile.setToDate(toDate);
			uploadedFile.setStatus(selectedStatus);
			uploadedFile.setUsername(selectedUser);
			uploadedFile.setUserId(ul.getCurrentUser().getId());
			uploadedFile.setPeriodCriteria(bundle.getString("fina2.web.by.uploaded.time"));
			ArrayList<String> props = new ArrayList<String>();
			props.add("fina2.xls.max.size");
			props.add("fina2.zip.max.size");
			props.add("fina2.mfb.xls.name.pattern");
			props.add("fina2.mfb.xls.historic.name.pattern");
			List<SysProperty> prs = sysPropLocal.findProperties(props);

			props.clear();
			if (prs != null) {
				validationProperties = new HashMap<String, String>();
				for (int i = 0; i < prs.size(); i++) {
					validationProperties.put(prs.get(i).getPropKey(), prs.get(i).getValue());
				}
			}

			BigDecimal userId = ul.getUserId(selectedUser);
			List<String> perms = ul.getUserPermissions(userId);

			patterns = XLSValidator.loadValidPatterns(UserUtil.getUserType(selectedUser, perms), ul.loadUserFiTypes(userId), null, sysPropLocal.findPropValue("fina2.dcs.matrix.path"));
			loadUsers(perms);
			loadBanks(perms);
			loadStatuses();
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
	}

	public List<String> getPatterns() {
		return patterns;
	}

	public void setPatterns(List<String> patterns) {
		this.patterns = patterns;
	}

	public Map<String, String> getValidationProperties() {
		return validationProperties;
	}

	public void setValidationProperties(Map<String, String> validationProperties) {
		this.validationProperties = validationProperties;
	}

	public long getAll() {
		return all;
	}

	public void setAll(long all) {
		this.all = all;
	}

	public UploadedFile getUploadedFile() {
		return uploadedFile;
	}

	public void setUploadedFile(UploadedFile uploadedFile) {
		this.uploadedFile = uploadedFile;
	}

	public long getConverted() {
		return converted;
	}

	public void setConverted(long converted) {
		this.converted = converted;
	}

	public long getRejected() {
		return rejected;
	}

	public void setRejected(long rejected) {
		this.rejected = rejected;
	}

	public long getUploaded() {
		return uploaded;
	}

	public void setUploaded(long uploaded) {
		this.uploaded = uploaded;
	}

	public long getUploadedAndConverted() {
		return uploadedAndConverted;
	}

	public void setUploadedAndConverted(long uploadedAndConverted) {
		this.uploadedAndConverted = uploadedAndConverted;
	}

	public long getUploadedErrorInProcessing() {
		return uploadedErrorInProcessing;
	}

	public void setUploadedErrorInProcessing(long uploadedErrorInProcessing) {
		this.uploadedErrorInProcessing = uploadedErrorInProcessing;
	}

	public long getUploadedAndNotConverted() {
		return uploadedAndNotConverted;
	}

	public void setUploadedAndNotConverted(long uploadedAndNotConverted) {
		this.uploadedAndNotConverted = uploadedAndNotConverted;
	}

	public long getUploadedAndNotValidated() {
		return uploadedAndNotValidated;
	}

	public void setUploadedAndNotValidated(long uploadedAndNotValidated) {
		this.uploadedAndNotValidated = uploadedAndNotValidated;
	}

	public long getUploadedAndProcessed() {
		return uploadedAndProcessed;
	}

	public void setUploadedAndProcessed(long uploadedAndProcessed) {
		this.uploadedAndProcessed = uploadedAndProcessed;
	}

	public long getUploadedAndValidated() {
		return uploadedAndValidated;
	}

	public void setUploadedAndValidated(long uploadedAndValidated) {
		this.uploadedAndValidated = uploadedAndValidated;
	}

	public String getFileToRemove() {
		return fileToRemove;
	}

	public void setFileToRemove(String fileToRemove) {
		this.fileToRemove = fileToRemove;
	}

	public List<SelectItem> getUsers() {

		return users;
	}

	public void setUsers(List<SelectItem> users) {
		this.users = users;
	}

	public void loadStatuses() {
		statuses = new ArrayList<SelectItem>();
		if (statuses.size() == 0) {
			statuses.add(new SelectItem("ALL", "-1"));

			statuses.add(new SelectItem(bundle.getString("fina2.web.uploaded"), "" + UploadFileStatus.UPLOADED.ordinal()));
			statuses.add(new SelectItem(bundle.getString("fina2.web.uploaded.validated"), "" + UploadFileStatus.UPLOADED_VALIDATED.ordinal()));
			statuses.add(new SelectItem(bundle.getString("fina2.web.uploaded.not.validated"), "" + UploadFileStatus.UPLOADED_NOT_VALIDATED.ordinal()));
			statuses.add(new SelectItem(bundle.getString("fina2.web.uploaded.converted"), "" + UploadFileStatus.UPLOADED_CONVERTED.ordinal()));
			statuses.add(new SelectItem(bundle.getString("fina2.web.uploaded.not.converted"), "" + UploadFileStatus.UPLOADED_NOT_CONVERTED.ordinal()));

		}
	}

	public void loadUsers(List<String> perms) {
		try {
			log.info("Loading users");
			users = new ArrayList<SelectItem>();
			List<String> usersList = ul.getAllLogins();

			ul = (UserLocal) Component.getInstance("userSession");
			User u = ul.getCurrentUser();
			selectedUser = u.getLogin();
			UserType ut = UserUtil.getUserType(selectedUser, perms);
			if (ut == UserType.INTERNAL) {
				users.add(new SelectItem(selectedUser));
				users.add(new SelectItem("ALL"));
			} else if (ut == UserType.EXTERNAL) {
				users.add(new SelectItem(selectedUser));
			} else if (ut == UserType.ADMINISTRATOR) {
				users.add(new SelectItem("ALL"));
				for (int i = 0; i < usersList.size(); i++) {
					users.add(new SelectItem(usersList.get(i)));
				}
			} else {
				users.add(new SelectItem(selectedUser));
			}
			log.info("Users loaded");
		} catch (Exception ex) {
			log.error("Error During Loading users");
			log.error(ex.getMessage(), ex);
		}

	}

	public void loadBanks(List<String> perms) {
		try {
			log.info("Loading Banks");
			banks = new ArrayList<SelectItem>();

			List<String> userBanks = null;
			User currUser = ul.getCurrentUser();

			if (currUser.getLogin().toLowerCase().trim().equals("sa")) {

				banks.add(new SelectItem("ALL"));
				List<String> bCodes = bankLocal.getAllBankCodes();
				if ((bCodes != null) && (bCodes.size() > 0)) {
					// selectedBank = bCodes.get(0);
					selectedBank = "ALL";
					banks.add(new SelectItem("UNKNOWN"));
					for (int i = 0; i < bCodes.size(); i++) {
						banks.add(new SelectItem(bCodes.get(i)));
					}
				}
			} else {
				UserType ut = UserUtil.getUserType(currUser.getLogin(), perms);

				userBanks = sysUserBankLocal.getAllUsersBankCodes(ul.getCurrentUser().getId());
				selectedBank = bundle.getString("fina2.dcs.user.myfis");
				if ((userBanks != null) && (userBanks.size() > 0)) {
					if (ut == UserType.EXTERNAL) {
						selectedBank = userBanks.get(0);
					}
					banks.add(new SelectItem(bundle.getString("fina2.dcs.user.myfis")));
					banks.add(new SelectItem("UNKNOWN"));
					for (int i = 0; i < userBanks.size(); i++) {
						banks.add(new SelectItem(userBanks.get(i)));
					}
				}

			}
			uploadedFile.setBankCode(selectedBank);

			log.info("Banks Loaded");
		} catch (Exception ex) {
			log.error("Error During loading banks\n");
			log.error(ex.getMessage(), ex);
		}

	}

	public List<SelectItem> getBanks() {
		return banks;
	}

	public void setBanks(List<SelectItem> banks) {
		this.banks = banks;
	}

	public List<SelectItem> getStatuses() {

		return statuses;
	}

	public List<SelectItem> getPeriodCriterias() {
		periodCriterias = new ArrayList<SelectItem>();
		periodCriterias.add(new SelectItem(bundle.getString("fina2.web.by.period"), "fina2.web.by.period"));
		periodCriterias.add(new SelectItem(bundle.getString("fina2.web.by.uploaded.time"), "fina2.web.by.uploaded.time"));

		return periodCriterias;
	}

	public void setPeriodCriterias(List<SelectItem> periodCriterias) {
		this.periodCriterias = periodCriterias;
	}

	public ArrayList<Long> getFilesToRemove() {
		return filesToRemove;
	}

	public void setFilesToRemove(ArrayList<Long> filesToRemove) {
		this.filesToRemove = filesToRemove;
	}

	public void setStatuses(List<SelectItem> statuses) {
		this.statuses = statuses;
	}

	public int getPageIndex() {
		return pageIndex;
	}

	public void setPageIndex(int pageIndex) {
		this.pageIndex = pageIndex;
	}

	public int getMaxPages() {
		return maxPages;
	}

	public void setMaxPages(int maxPages) {
		this.maxPages = maxPages;
	}

	public String getFilename() {
		return filename;
	}

	public void setFilename(String filename) {
		this.filename = filename;
	}

	public List<UploadedFile> getFiles() {
		return files;
	}

	public String getUsername() {
		return username;
	}

	public Date getToDate() {
		return toDate;
	}

	public Date getFromDate() {
		return fromDate;
	}

	public String getSelectedStatus() {
		return selectedStatus;
	}

	public String getSelectedUser() {
		return selectedUser;
	}

	public String getSelectedBank() {
		return selectedBank;
	}

	public void setFiles(List<UploadedFile> files) {
		this.files = files;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setToDate(Date toDate) {
		this.toDate = toDate;
	}

	public void setFromDate(Date fromDate) {
		this.fromDate = fromDate;
	}

	public void setSelectedStatus(String selectedStatus) {
		this.selectedStatus = selectedStatus;
	}

	public void setSelectedUser(String selectedUser) {
		this.selectedUser = selectedUser;
	}

	public void setSelectedBank(String selectedBank) {
		this.selectedBank = selectedBank;
	}

	public void removeOneFile(ActionEvent e) {
		String name = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("file_to_remove").toString();
		for (int i = 0; i < invalidFiles.size(); i++) {
			if (invalidFiles.get(i).trim().equals(name.trim())) {
				invalidFiles.remove(i);

				File f = new File(name);
				if (f.exists())
					f.delete();
			}
		}
	}

	public void fileSelected(Long id) {
		if (filesToRemove.contains(id))
			filesToRemove.remove((Object) id);
		else
			filesToRemove.add(id);
	}

	public void removeFiles(String ids) {
		System.out.println("###################" + ids);
	}

	public void viewValidation(int id) {
		try {

			ufl = (UploadedFileLocal) Component.getInstance("uploadFileSession");

			UploadedFile uf = ufl.findByPrimaryKey(id);
			setXlsMatrixValid(uf.getMatrixValid());
			if (xlsMatrixValid) {
				setMatrixReason(null);
				setXlsFile(uf.isExcelVersionValid());
				setXlsFileNameValid(uf.isNameValid());
				setXlsProtected(((uf.getProtectionInfo() != null) && (uf.getProtectionInfo().trim().equals("[]")) ? true : false));
				setUnconfirmedSheets((uf.getProtectionInfo() != null) ? uf.getProtectionInfo().trim() : "");
				setXlsProtPasswValid(((uf.getPasswordInfo() != null) && (uf.getPasswordInfo().trim().equals("[]")) ? true : false));

				setHasUserBank((uf.isHasUserBank() != null) ? (uf.isHasUserBank()) : false);
			} else {
				setXlsFile(uf.isExcelVersionValid());
				setXlsFileNameValid(uf.isNameValid());
				setXlsProtected(false);
				setUnconfirmedSheets((uf.getProtectionInfo() != null) ? uf.getProtectionInfo().trim() : "");
				setXlsProtPasswValid(false);

				setHasUserBank((uf.isHasUserBank() != null) ? (uf.isHasUserBank()) : false);
				setMatrixReason(uf.getReason());
			}
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
	}

	public boolean isHasUserBank() {
		return hasUserBank;
	}

	public void setHasUserBank(boolean hasUserBank) {
		this.hasUserBank = hasUserBank;
	}

	public boolean isXlsProtPasswValid() {
		return xlsProtPasswValid;
	}

	public void setXlsProtPasswValid(boolean xlsProtPasswValid) {
		this.xlsProtPasswValid = xlsProtPasswValid;
	}

	public boolean isXlsProtected() {
		return xlsProtected;
	}

	public void setXlsProtected(boolean xlsProtected) {
		this.xlsProtected = xlsProtected;
	}

	public boolean isXlsFileNameValid() {
		return xlsFileNameValid;
	}

	public void setXlsFileNameValid(boolean xlsFileNameValid) {
		this.xlsFileNameValid = xlsFileNameValid;
	}

	public boolean isXlsFile() {
		return xlsFile;
	}

	public void setXlsFile(boolean xlsFile) {
		this.xlsFile = xlsFile;
	}

	public boolean isXlsMatrixValid() {
		return xlsMatrixValid;
	}

	public void setXlsMatrixValid(boolean xlsMatrixValid) {
		this.xlsMatrixValid = xlsMatrixValid;
	}

	public String getMatrixReason() {
		return matrixReason;
	}

	public void setMatrixReason(String matrixReason) {
		this.matrixReason = matrixReason;
	}

	public BigDecimal getSelectedUserId() {
		return selectedUserId;
	}

	public void setSelectedUserId(BigDecimal selectedUserId) {
		this.selectedUserId = selectedUserId;
	}

}